﻿using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Wicresoft.RDW.DataAccess;
using Wicresoft.RDW.Interface;

namespace Wicresoft.RDW.Business
{
    public class BaseBiz<T> where T : EntityObject
    {
        protected ObjectSet<T> Context
        {
            get
            {
                InitContext();
                return _ctx;
            }
        } private ObjectSet<T> _ctx;

        protected void InitContext()
        {
            RDW.DataAccess.RDWEntities db = new RDWEntities();
            _ctx = db.CreateObjectSet<T>(typeof(T).Name);
        }

        protected void SubmitChanges()
        {
            try
            {
                _ctx.Context.SaveChanges();
                _ctx.Context.AcceptAllChanges();
            }
            catch
            {
                throw;
            }
            finally
            {
                _ctx.Context.Dispose();
                _ctx = null;
            }
        }
        
        public T GetByCondition(Expression<Func<T, bool>> condition)
        {
            return this.Context.Where<T>(condition).FirstOrDefault<T>();
        }

        public List<T> GetList(Expression<Func<T, bool>> condition)
        {
            return this.Context.Where<T>(condition).ToList<T>();
        }

        public List<T> GetList()
        {
            return this.Context.ToList<T>();
        }

        public PagedList<T> GetPaged(int pageIndex, int pageSize)
        {
            return this.GetPaged(pageIndex, pageSize, p => true);
        }

        public PagedList<T> GetPaged(int pageIndex, int pageSize, Expression<Func<T, bool>> expression)
        {
            var qry = this.Context.Where<T>(expression);
            var count = qry.Count();
            var qryRet = qry.ToList<T>().Skip(pageIndex * pageSize).Take(pageSize);
            return new PagedList<T>(qryRet, count, pageIndex, pageSize);
        }

        public PagedList<T> GetPaged<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> expression, Expression<Func<T, TKey>> orderBy, bool isDesc)
        {
            var qry = default(IQueryable<T>);
            if (!isDesc)
                qry = this.Context.OrderBy(orderBy).Where(expression);
            else
                qry = this.Context.OrderByDescending(orderBy).Where(expression);

            var count = qry.Count();
            qry = qry.Skip(pageIndex * pageSize).Take(pageSize);
            return new PagedList<T>(qry, count, pageIndex, pageSize);
        }

        public PagedList<T> GetPaged(List<T> qry, int count, int pageIndex, int pageSize)
        {
            var qryRet = qry.Skip(pageIndex * pageSize).Take(pageSize);
            return new PagedList<T>(qryRet, count, pageIndex, pageSize);
        }

        public PagedList<T> GetPaged<TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy, bool isDesc)
        {
            return this.GetPaged(pageIndex, pageSize, p => true, orderBy, isDesc);
        }

        public void Create(T t)
        {
            try
            {
                InitContext();
                _ctx.AddObject(t);
                SubmitChanges();
            }
            catch
            {
                throw;
            }
        }

        public void Update(T t)
        {
            try
            {
                InitContext();
                _ctx.Context.GetObjectByKey(t.EntityKey);
                _ctx.ApplyCurrentValues(t);
                SubmitChanges();
            }
            catch
            {
                throw;
            }
        }

        public void Delete(T t)
        {
            if (t == null) return;
            try
            {
                InitContext();
                _ctx.Context.Attach(t);
                _ctx.Context.DeleteObject(t);
                SubmitChanges();
            }
            catch
            {
                throw;
            }
        }

        public void Delete(List<T> ts)
        {
            if (ts.Count < 1) return;

            InitContext();
            
            foreach (var t in ts)
            {
                try
                {
                    _ctx.Context.Attach(t);
                    _ctx.Context.DeleteObject(t);
                    _ctx.DeleteObject(t);
                }
                catch
                {
                    throw;
                }
            }
            SubmitChanges();
        }

       
    }
}
